package com.bjb.vr.common.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.common.ao.ResBundleAo;
import com.bjb.vr.common.ao.ResCusContentAuthorityAo;
import com.bjb.vr.common.ao.ResPackageDetailAo;
import com.bjb.vr.common.ao.ResPackageDetailRemoveAo;
import com.bjb.vr.common.constant.ThreadLocalConstant;
import com.bjb.vr.common.dto.*;
import com.bjb.vr.common.mapper.OptProdBundleDetailMapper;
import com.bjb.vr.common.mapper.ResBundleDetailMapper;
import com.bjb.vr.common.mapper.ResBundleMapper;
import com.bjb.vr.common.result.BaseResult;
import com.bjb.vr.common.result.CommonResult;
import com.bjb.vr.common.utils.PageUtils;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.*;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author admin
 * @description 针对表【res_bundle(资源包表)】的数据库操作Service
 * @createDate 2022-04-19 10:42:29
 */

@Service
public class ResBundleService extends ServiceImpl<ResBundleMapper, ResBundle> {

    @Resource
    private ResBundleMapper resBundleMapper;

    @Resource
    private ResDictionaryService dictionaryService;

    @Resource
    private SysTenantService tenantService;

    @Resource
    private ResBundleDetailMapper resBundleDetailMapper;

    @Resource
    private ResBundleDetailService resBundleDetailService;

    @Resource
    private OptProdBundleDetailMapper optProdBundleDetailMapper;


    /**
     * 获取设备更新资源包列表
     *
     * @param udid
     * @return
     */
    public BaseResult<List<ClientResBundleVo>> getUpdateResBundleAndContentByUdid(String udid) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        BaseResult<List<ClientResBundleVo>> result = new CommonResult<List<ClientResBundleVo>>(false);

        List<ClientResBundleVo> resBundleVoList = new ArrayList<>();

        List<ClientResBundleContentVo> resBundleContentVoList = resBundleMapper.getUpdateResBundleAndContentByUdid(udid);
        resBundleVoList = convertClientResCoursePoToVo(resBundleContentVoList);
        if (resBundleVoList != null && !resBundleVoList.isEmpty()) {
            result = CommonResult.Ok().setResult(resBundleVoList);
        } else {
            result = CommonResult.Fail("未找到需要更新的资源");
        }
        return result;
    }

    /**
     * 获取设备更新资源包列表
     *
     * @param udid
     * @return
     */
    public BaseResult<Long[]> getUpdateResBundleIdsByUdid(String udid) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        BaseResult<Long[]> result = new CommonResult<Long[]>(false);
        Set<Long> resBundleIds = new HashSet<>();
        Long[] arrayBundleId = null;
        List<ResBundle> resBundleList = resBundleMapper.getUpdateResBundleByUdid(udid);
        if (resBundleList != null && !resBundleList.isEmpty()) {
            resBundleList.stream().forEach(resBundle -> resBundleIds.add(resBundle.getId()));
            arrayBundleId = new Long[resBundleIds.size()];
            resBundleIds.toArray(arrayBundleId);
            result = CommonResult.Ok().setResult(arrayBundleId);
        } else {
            result = CommonResult.Fail("未找到需要更新的资源包");
        }
        return result;
    }


    /**
     * 数据类型转换
     *
     * @param resBundleContentVoList
     * @return
     */
    private List<ClientResBundleVo> convertClientResCoursePoToVo(List<ClientResBundleContentVo> resBundleContentVoList) {
        List<ClientResBundleVo> resBundleVoList = new ArrayList<>();
        Map<Long, List<ClientResContentVo>> map = new HashMap<>();
        if (!resBundleContentVoList.isEmpty()) {
            resBundleContentVoList.stream().forEach(resBundleContentVo -> {
                if (resBundleContentVo.getContentId() != null) {
                    ClientResBundleVo clientResBundleVo = new ClientResBundleVo();
                    clientResBundleVo.setResBundleId(resBundleContentVo.getResBundleId());
                    ClientResContentVo clientResContentVo = new ClientResContentVo();
                    BeanUtils.copyProperties(resBundleContentVo, clientResContentVo);
                    if (map.containsKey(clientResBundleVo.getResBundleId())) {

                        map.get(clientResBundleVo.getResBundleId()).add(clientResContentVo);
                    } else {
                        List<ClientResContentVo> clientResContentVoList = new ArrayList<>();
                        clientResContentVoList.add(clientResContentVo);
                        map.put(clientResBundleVo.getResBundleId(), clientResContentVoList);
                    }
                }
            });

            for (Long key : map.keySet()) {
                ClientResBundleVo clientResBundleVo = new ClientResBundleVo();
                clientResBundleVo.setResBundleId(key);
                clientResBundleVo.setClientResContentVoList(map.get(key));
                resBundleVoList.add(clientResBundleVo);
            }
        }
        return resBundleVoList;
    }

    /**
     * 资源包列表
     *
     * @return
     */
    public IPage<ResPackageVo> getPackageResources() {
        List<ResPackageVo> resPackageVos = resBundleMapper.getPackageResources();
        IPage<ResPackageVo> voIPage = new Page<>(1, 10, resPackageVos.size());
        voIPage.setRecords(resPackageVos);
        return voIPage;
    }

    /**
     * 查询资源包列表
     *
     * @param resBundleAo
     * @return
     */
    public IPage<ResBundleVo> queryBundleList(ResBundleAo resBundleAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        LambdaQueryWrapper<ResBundle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(resBundleAo.getResBundleName()), ResBundle::getResBundleName, resBundleAo.getResBundleName());
        queryWrapper.eq(StringUtils.isNotBlank(resBundleAo.getTenantId()), ResBundle::getTenantId, resBundleAo.getTenantId());
        queryWrapper.groupBy(ResBundle::getResBundleName);
        Page<ResBundle> resBundlePage = resBundleMapper.selectPage(new Page<>(resBundleAo.getCurrent(), resBundleAo.getSize()), queryWrapper);
        Page<ResBundleVo> resBundleVoPage = buildBundleInfo(resBundlePage);
        return resBundleVoPage;
    }

    /**
     * 封装资源包属性
     *
     * @param resBundlePage
     * @return
     */
    private Page<ResBundleVo> buildBundleInfo(Page<ResBundle> resBundlePage) {
        Page<ResBundleVo> resBundleVoPage = new Page<>(resBundlePage.getCurrent(), resBundlePage.getSize(), resBundlePage.getTotal());
        List<ResBundle> records = resBundlePage.getRecords();
        List<ResBundleVo> resBundleVos = new ArrayList<>();
        records.stream().forEach(res -> {
            ResBundleVo resBundleVo = new ResBundleVo();
            BeanUtils.copyProperties(res, resBundleVo);
            // 查询资源包类型
            resBundleVo.setResBundleType(res.getBundleType());
            String dictName = dictionaryService.getResDictionaryByCode(res.getBundleType()).getDictName();
            if (StringUtils.isNotBlank(dictName)) {
                resBundleVo.setResBundleTypeName(dictName);
            }
            // 查询所属
            LambdaQueryWrapper<ResBundle> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ResBundle::getResBundleName, res.getResBundleName());
            List<ResBundle> bundleList = resBundleMapper.selectList(queryWrapper);
            List<String> tenantList = bundleList.stream().map(ResBundle::getTenantId).collect(Collectors.toList());
            StringBuilder tenantBuilder = new StringBuilder();
            for (String tenantId : tenantList) {
                if (StringUtils.isNotBlank(tenantId)){
                    SysTenant sysTenant = tenantService.selectOneSysTenantByTenantId(tenantId);
                    if (Objects.nonNull(sysTenant)) {
                        tenantBuilder.append(sysTenant.getTenantName());
                        tenantBuilder.append(",");
                    }
                }
            }
            if (tenantBuilder.length() > 1){
                tenantBuilder.deleteCharAt(tenantBuilder.lastIndexOf(","));
            }
            resBundleVo.setTenantName(tenantBuilder.toString());
            resBundleVos.add(resBundleVo);
        });
        resBundleVoPage.setRecords(resBundleVos);
        return resBundleVoPage;
    }

    /**
     * 新建资源包
     *
     * @param resBundleAo
     * @return
     */
    public boolean addResBundle(ResBundleAo resBundleAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        try {
            // 新建资源包
            ResBundle resBundle = new ResBundle();
            BeanUtils.copyProperties(resBundleAo, resBundle);
            resBundle.setCreator(umsAccountVo.getNickName());
            resBundleMapper.insert(resBundle);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 查询该组织是否已经有资源包
     *
     * @return
     */
    public boolean queryResBundle(ResBundleAo resBundleAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        LambdaQueryWrapper<ResBundle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ResBundle::getResBundleName, resBundleAo.getResBundleName());
        try {
            List<ResBundle> resBundles = resBundleMapper.selectList(queryWrapper);
            if (resBundles.size() > 0) {
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 编辑资源包
     *
     * @param resBundleAo
     * @return
     */
    public boolean updateResBundle(ResBundleAo resBundleAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        try {
            ResBundle resBundle = new ResBundle();
            BeanUtils.copyProperties(resBundleAo, resBundle);
            resBundleMapper.updateById(resBundle);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 查询资源包--单条
     *
     * @param resBundleAo
     * @return
     */
    public ResBundleVo queryResBundleOne(ResBundleAo resBundleAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        ResBundle resBundle = resBundleMapper.selectById(resBundleAo.getId());
        ResBundleVo resBundleVo = new ResBundleVo();
        BeanUtils.copyProperties(resBundle, resBundleVo);
        return resBundleVo;
    }

    /**
     * 查询资源包详情
     *
     * @param resBundleAo
     * @return
     */
    public IPage<ResBundleDetailVo> queryResBundleDetail(ResBundleAo resBundleAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        // 字典值查询替换
        MPJLambdaWrapper<ResBundleDetailVo> joinQuery = new MPJLambdaWrapper<>();
        joinQuery.select(ResBundleDetail::getId)
                .select(ResBundleDetail::getResBundleId)
                .selectAs(ResBundleDetail::getContentId, "resId")
                .selectAs(ResBundleDetail::getContentSize, "capacity")
                .selectAs(ResContent::getName, "resName")
                .selectAs(ResContent::getDicPeriodCode, "period")
                .selectAs(ResContent::getDicLevelCode, "level")
                .selectAs(ResContent::getDicSubjectCode, "subject")
                .selectAs(ResContent::getDicTypeCode, "resBundleTypeName")
                .leftJoin(ResContent.class, ResContent::getId, ResBundleDetail::getContentId);
        // 查询条件
        joinQuery.eq(Objects.nonNull(resBundleAo.getId()), ResBundleDetail::getResBundleId, resBundleAo.getId());
        joinQuery.like(StringUtils.isNotBlank(resBundleAo.getResName()), ResContent::getName, resBundleAo.getResName());
        joinQuery.groupBy(ResBundleDetail::getContentId);
        // 查询资源包名称
        ResBundle resBundle = resBundleMapper.selectById(resBundleAo.getId());
        // 执行查询
        IPage<ResBundleDetailVo> joinPage = resBundleDetailMapper.selectJoinPage(new Page<>(resBundleAo.getCurrent(), resBundleAo.getSize()), ResBundleDetailVo.class, joinQuery);
        buildVoInfo(joinPage, resBundle);
        return joinPage;
    }

    /**
     * 封装返回字典值
     *
     * @param joinPage
     * @param resBundle
     * @return
     */
    private void  buildVoInfo(IPage<ResBundleDetailVo> joinPage, ResBundle resBundle){
        List<ResBundleDetailVo> records = joinPage.getRecords();
        for (ResBundleDetailVo record : records) {
            record.setResBundleName(resBundle.getResBundleName());
            if (StringUtils.isNotBlank(record.getPeriod())){
                record.setPeriod(dictionaryService.getResDictionaryByCode(record.getPeriod()).getDictName());
            }
            if (StringUtils.isNotBlank(record.getLevel())){
                record.setLevel(dictionaryService.getResDictionaryByCode(record.getLevel()).getDictName());
            }
            if (StringUtils.isNotBlank(record.getSubject())){
                record.setSubject(dictionaryService.getResDictionaryByCode(record.getSubject()).getDictName());
            }
            if (StringUtils.isNotBlank(record.getResBundleTypeName())){
                record.setResBundleTypeName(dictionaryService.getResDictionaryByCode(record.getResBundleTypeName()).getDictName());
            }
        }
    }

    /**
     * 资源包添加新资源
     *
     * @param resBundleAo
     * @return
     */
    public boolean addResBundleDetail(ResBundleAo resBundleAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        List<ResBundleAo.ResArray> resArray = resBundleAo.getResArray();
        try {
            // 1、添加资源到资源包
            for (ResBundleAo.ResArray array : resArray) {
                ResBundleDetail resBundleDetail = new ResBundleDetail();
                resBundleDetail.setResBundleId(resBundleAo.getId());
                resBundleDetail.setContentId(array.getResId());
                resBundleDetail.setContentSize(array.getCapacity());
                resBundleDetailService.save(resBundleDetail);
            }
            // 2、更新资源包大小
            ResBundle bundle = resBundleMapper.selectById(resBundleAo.getId());
            Integer capacityValue = resArray.stream().mapToInt(ResBundleAo.ResArray::getCapacity).sum();
            ResBundle resBundle = new ResBundle();
            resBundle.setId(resBundleAo.getId());
            resBundle.setCapacity(bundle.getCapacity() + capacityValue);
            resBundleMapper.updateById(resBundle);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 资源包删除已有资源
     *
     * @param resBundleAo
     * @return
     */
    public boolean removeResBundleDetail(ResBundleAo resBundleAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        try {
            ResPackageDetailRemoveAo removeAo = new ResPackageDetailRemoveAo();
            removeAo.setResBundleId(resBundleAo.getId());
            removeAo.setResIds(resBundleAo.getResIds());
            // 更新资源包大小
            Integer capacityValue = resBundleDetailMapper.sumResCapacity(removeAo);
            ResBundle bundle = resBundleMapper.selectById(resBundleAo.getId());
            ResBundle resBundle = new ResBundle();
            resBundle.setId(resBundleAo.getId());
            resBundle.setCapacity(bundle.getCapacity() - capacityValue);
            resBundleMapper.updateById(resBundle);
            // 从资源包删除
            resBundleDetailMapper.deleteByResBundleId(removeAo);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     *
     * @param resBundleAo
     * @return
     */
    public IPage<ResBundleDetailVo> queryOtherResBundleDetail(ResBundleAo resBundleAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        PageUtils.setPageNo(resBundleAo);
        ResPackageDetailAo resPackageDetailAo = new ResPackageDetailAo();
        BeanUtils.copyProperties(resBundleAo,resPackageDetailAo);
        resPackageDetailAo.setResBundleId(resBundleAo.getId());
        List<ResPackageDetailVo> resPackageDetailVos = resBundleDetailMapper.queryOptPackageResources(resPackageDetailAo);
        Integer resPackageDetailVosSize = resBundleDetailMapper.queryOptPackageResourcesSize(resPackageDetailAo);

        // 数据封装
        List<ResBundleDetailVo> resPackageResourcesVos = new ArrayList<>();
        resPackageDetailVos.stream().forEach(rsd -> {
            resPackageResourcesVos.add(new ResBundleDetailVo(rsd.getResId(), rsd.getResName(), rsd.getCapacity()));
        });
        IPage<ResBundleDetailVo> voIPage = new Page<>(resBundleAo.getCurrent(), resBundleAo.getSize(), resPackageDetailVosSize);
        voIPage.setRecords(resPackageResourcesVos);
        return voIPage;
    }

    /**
     * 获取所有资源包列表（多个租户合并为一条记录）
     * @return
     */
    public List<ResBundle> queryResBundleList(){
        List<ResBundle> resBundleList = resBundleMapper.queryResBundleList();
        return resBundleList;
    }


    /**
     * 查询资源授权资源包列表（资源授权管理-选择产品包列表）
     *
     * @param resCusContentAuthorityAo
     * @return
     */
    public IPage<ResBundleVo> queryResourceAuthorityBundleList(ResCusContentAuthorityAo resCusContentAuthorityAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        LambdaQueryWrapper<ResBundle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(resCusContentAuthorityAo.getResBundleName()), ResBundle::getResBundleName, resCusContentAuthorityAo.getResBundleName());
        Page<ResBundle> resBundlePage = resBundleMapper.selectPage(new Page<>(resCusContentAuthorityAo.getCurrent(), resCusContentAuthorityAo.getSize()), queryWrapper);
        Page<ResBundleVo> resBundleVoPage = buildBundleInfo(resBundlePage);
        return resBundleVoPage;
    }

    /**
     * 资源授权管理-获取多个资源包资源列表
     *
     * @param resCusContentAuthorityAo
     * @return
     */
    public List<ResContent> queryAuthorityBundleResourceList(ResCusContentAuthorityAo resCusContentAuthorityAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        // 字典值查询替换
        MPJLambdaWrapper<ResContent> joinQuery = new MPJLambdaWrapper<>();
        joinQuery.select(ResContent::getId)
                .select(ResContent::getName)
                .leftJoin(ResContent.class, ResContent::getId, OptProdBundleDetail::getContentId);
        // 查询条件
        joinQuery.in(OptProdBundleDetail::getResBundleId,resCusContentAuthorityAo.getResBundleIds());
        joinQuery.groupBy(OptProdBundleDetail::getContentId);

        // 执行查询
        List<ResContent> resContentList = optProdBundleDetailMapper.selectJoinList(ResContent.class,joinQuery);
        return resContentList;
    }

}
